#include "datapackage.h"

#include "datapackage.h"

// 构造函数
DataPackage::DataPackage()
{
    qRegisterMetaType<DataPackage>("DataPackage");
    this->timeStmp = "";
    this->data_length=0;
    this->package_type=0;
    this->pkt_content=nullptr;
}

// 设置数据包长度
void DataPackage::setDataLength(u_int data_length)
{
    this->data_length = data_length;
}

// 设置时间戳
void DataPackage::setTimeStmp(QString timeStmp)
{
    this->timeStmp = timeStmp;
}

// 设置信息
void DataPackage::setInfo(QString info)
{
    this->info = info;
}

// 设置包类型
void DataPackage::setPackageType(int type)
{
    this->package_type = type;
}

// 设置数据包内容指针
void DataPackage::setPointer(const u_char *pkt_content, int size)
{
    this->pkt_content = (u_char*)malloc(size);
    if(this->pkt_content!=nullptr)
    {
        memcpy((char*)(this->pkt_content), pkt_content, size);
    }
    else
    {
        this->pkt_content = nullptr;
    }
    
}
/*************** 获取数据包数据 ***********************/
// 获取数据包长度
QString DataPackage::getDataLength()
{
    return QString::number(this->data_length);
}

// 获取时间戳
QString DataPackage::getTimeStmp()
{
    return this->timeStmp;
}

// 获取信息
QString DataPackage::getInfo()
{
    return this->info;
}

// 获取包类型
QString DataPackage::getPackageType()
{
    switch (this->package_type) {
    case 1:
        return "ARP";
        break;
    case 2:
        return "ICMP";
        break;
    case 3:
        return "TCP";
        break;
    case 4:
        return "UDP";
        break;
    case 5:
        return "DNS";
        break;
    case 6:
        return "TLS";
        break;
    case 7:
        return "SSL";
        break;
    default:
        return "";
        break;
    }
}

// 获取源地址
QString DataPackage::getSource()
{
    if (this->package_type == 1)
        return getSrcMacAddr();
    else return getSrcIpAddr();
}

// 获取目标地址
QString DataPackage::getDestination()
{
    if (this->package_type == 1)
        return getDesMacAddr();
    else return getDesIpAddr();
}

// 获取数据包长度（整数）
u_int DataPackage::getDataLengthInt()
{
    return this->data_length;
}

// 获取包类型（整数）
int DataPackage::getPackageTypeInt()
{
    return this->package_type;
}
/*************** 获取mac数据 ***********************/
// 获取目标MAC地址
QString DataPackage::getDesMacAddr()
{
    // 获取以太网头部
    ETHER_HEADER* eth;
    eth = (ETHER_HEADER*)pkt_content;
    
    // 获取目标MAC地址
    u_char* addr = eth->_ether_dhost;
    
    if(addr)
    {
        // 将MAC地址转换为字符串格式
        QString res = byteToString(addr,1) + ":"
        + byteToString(addr+1,1) + ":"
        + byteToString(addr+2,1) + ":"
        + byteToString(addr+3,1) + ":"
        + byteToString(addr+4,1) + ":"
                      + byteToString(addr+5,1);
        
        // 检查是否为广播地址
        if (res == "FF:FF:FF:FF:FF:FF")
            return "FF:FF:FF:FF:FF:FF(Broadcast)"; // 返回广播地址
        else 
            return res; // 返回目标MAC地址
    }
    
    // 如果无法获取地址，返回空字符串
    return "";
}

// 获取源MAC地址
QString DataPackage::getSrcMacAddr()
{
    ETHER_HEADER* eth;
    eth = (ETHER_HEADER*)pkt_content;


    u_char* addr = eth->_ether_shost;

    if(addr)
    {
        // 将MAC地址转换为字符串格式
        QString res = byteToString(addr,1) + ":"
                      + byteToString(addr+1,1) + ":"
                      + byteToString(addr+2,1) + ":"
                      + byteToString(addr+3,1) + ":"
                      + byteToString(addr+4,1) + ":"
                      + byteToString(addr+5,1);

        // 检查是否为广播地址
        if (res == "FF:FF:FF:FF:FF:FF")
            return "FF:FF:FF:FF:FF:FF(Broadcast)"; // 返回广播地址
        else
            return res; // 返回目标MAC地址
    }

    // 如果无法获取地址，返回空字符串
    return "";
}

// 获取MAC类型
QString DataPackage::getMacType()
{
    ETHER_HEADER* eth;
    eth = (ETHER_HEADER*)(pkt_content); // 获取以太网头部
    u_short type = NTOHS(eth->_ether_type); // 获取以太网类型并转换字节序
	if (type == 0x0800)
		return "IPv4(0x0800)"; // 返回IPv4类型
	else if (type == 0x0806)
		return "ARP(0x0806)"; // 返回ARP类型
	else return ""; // 返回空字符串
}
/*************** 获取IP数据 ***********************/
// 获取IP相关信息
QList<QTreeWidgetItem *> DataPackage::getIp()
{
    // 获取IP版本
    QString ipVersion = getIpVersion();
    // 获取IP头部长度
    QString ipHeaderLength = getIpHeaderLength();
    // 获取IP总长度
    QString ipTotalLength = getIpTotalLength();
    // 获取IP协议
    QString ipProtocol = getIpProtocol();
    // 获取IP生存时间
    QString ipTTL = getIpTTL();
    // 获取源IP地址
    QString srcIp = getSrcIpAddr();
    // 获取目标IP地址
    QString desIp = getDesIpAddr();
    // 创建QTreeWidgetItem列表
    QList<QTreeWidgetItem*> info;
    // 添加IP版本信息
    info.append(new QTreeWidgetItem(QStringList() << ipVersion));
    // 添加IP头部长度信息
    info.append(new QTreeWidgetItem(QStringList() << ipHeaderLength));
    // 添加IP总长度信息
    info.append(new QTreeWidgetItem(QStringList() << ipTotalLength));
    // 添加IP生存时间信息
    info.append(new QTreeWidgetItem(QStringList() << ipTTL));
    // 添加IP协议信息
    info.append(new QTreeWidgetItem(QStringList() << "Protocol :" + ipProtocol));
    // 添加源IP地址信息
    info.append(new QTreeWidgetItem(QStringList() << "Source Address :" + srcIp));
    // 添加目标IP地址信息
    info.append(new QTreeWidgetItem(QStringList() << "Destination Address :" + desIp));
    // 返回信息列表
    return info;
}

// 获取目标IP地址
QString DataPackage::getDesIpAddr()
{
    // 获取IP头部
    IP_HEADER* ip;
    ip = (IP_HEADER*)(pkt_content + 14);
    // 获取目标IP地址并转换字节序
    u_int addr = NTOHSL(ip->_desc);
    if (addr)
    {
        // 将IP地址转换为字符串格式
        QString res = iptos(addr);
        return res;
    }

}

// 获取源IP地址
QString DataPackage::getSrcIpAddr()
{
    // 获取IP头部
    IP_HEADER* ip;
    ip = (IP_HEADER*)(pkt_content + 14);
    // 获取源IP地址
    sockaddr_in srcAddr;
    srcAddr.sin_addr.s_addr = ip->_src;
    // 返回源IP地址字符串
    return QString(inet_ntoa(srcAddr.sin_addr));
}

// 获取IP版本
QString DataPackage::getIpVersion()
{
    // 获取IP头部
    IP_HEADER* ip;
    ip = (IP_HEADER*)(pkt_content + 14);
    // int protocol = ip->_protocol;
    char version = ip->_version_headerLen & 0xf0;
    if(version == 0x40)
    {
        return "Version:4";
    }

}

// 获取IP头部长度
QString DataPackage::getIpHeaderLength()
{
    IP_HEADER* ip;
    ip = (IP_HEADER*)(pkt_content + 14);
    // int protocol = ip->_protocol;
    char length = ip->_version_headerLen & 0x0f;
    QString res = "Header Length:" + QString::number(length * 4) + "bytes";
    return res;
}

// 获取IP总长度
QString DataPackage::getIpTotalLength()
{
    IP_HEADER* ip;
    ip = (IP_HEADER*)(pkt_content + 14);
    u_short totalLength = NTOHS(ip->_totalLen);
    return "Total Length:" + QString::number(totalLength);
}

// 获取IP生存时间
QString DataPackage::getIpTTL()
{
    IP_HEADER* ip;
    ip = (IP_HEADER*)(pkt_content + 14);
    u_char ttl = ip->_timeLive;
    return "Time to Live:" + QString::number(ttl);
}

// 获取IP协议
QString DataPackage::getIpProtocol()
{
    IP_HEADER* ip;
    ip = (IP_HEADER*)(pkt_content + 14);
    int protocol = ip->_protocol;
    switch(protocol)
    {
    case 1:
    {//icmp
        return "ICMP(1)";
    }
    case 6:
    {//tcp
        return "TCP(6)";
    }
    case 17:
    {//udp
        return "UDP(17)";
    }
    default:break;
    }
    return 0;
}



/*************** 获取ARP数据 ***********************/

QList<QTreeWidgetItem *> DataPackage::getArp()
{
    QList<QTreeWidgetItem*> info;
    QString hType = getArpHType();
    QString pType = getArpPType();
    QString sMacAddr = getArpSMacAddr();
    QString tMacAddr = getArpTMacAddr();
    QString sIpAddr = getArpSIpAddr();
    QString tIpAddr = getArpSIpAddr();
    QString Op = getArpOp();
    info.append(new QTreeWidgetItem(QStringList() << hType));
    info.append(new QTreeWidgetItem(QStringList() << pType));
    info.append(new QTreeWidgetItem(QStringList() << "Opcode: " + Op));
    info.append(new QTreeWidgetItem(QStringList() << sMacAddr));
    info.append(new QTreeWidgetItem(QStringList() << sIpAddr));
    info.append(new QTreeWidgetItem(QStringList() << tMacAddr));
    info.append(new QTreeWidgetItem(QStringList() << tIpAddr));
    return info;
}

QString DataPackage::getArpHType()
{
    ARP_HEADER* arp;
    arp = (ARP_HEADER*)(pkt_content + 14);
    u_short hType = NTOHS(arp->_type);
    QString res = "Hardware Type :";
    if (hType == 1)
    {
        res += "Ethernet(1)";
    }
    else
    {
        res += "(" + QString::number(hType) + ")";
    }
    return res;
}

QString DataPackage::getArpOp()
{
    ARP_HEADER* arp;
    arp = (ARP_HEADER*)(pkt_content + 14);
    u_short op = NTOHS(arp->_op_type);
    QString res = "";
    if (op == 1)
    {
        res = "request(1)";
    }
    else if (op == 2)
    {
        res = "reply(2)";
    }
    return res;
}

QString DataPackage::getArpPType()
{
    ARP_HEADER* arp;
    arp = (ARP_HEADER*)(pkt_content + 14);
    u_short protocol = NTOHS(arp->_protocol);
    if (protocol == 0x0800)
        return "Protocol Type: IPv4(0x0800)";
    else
        return "Protocol Type: " + QString::number(protocol);
}

QString DataPackage::getArpSMacAddr()
{
    ARP_HEADER* arp;
    arp = (ARP_HEADER*)(pkt_content + 14);
    u_char* addr = arp->_src_ether_addr;
    QString res = byteToString(addr, 1) + ":"
                  + byteToString(addr + 1, 1) + ":"
                  + byteToString(addr + 2, 1) + ":"
                  + byteToString(addr + 3, 1) + ":"
                  + byteToString(addr + 4, 1) + ":"
                  + byteToString(addr + 5, 1);
    return "Sender Mac Address: " + res;
}

QString DataPackage::getArpTMacAddr()
{
	ARP_HEADER* arp;
	arp = (ARP_HEADER*)(pkt_content + 14);
	u_char* addr = arp->_des_ether_addr;
	QString res = byteToString(addr, 1) + ":"
		+ byteToString(addr + 1, 1) + ":"
		+ byteToString(addr + 2, 1) + ":"
		+ byteToString(addr + 3, 1) + ":"
		+ byteToString(addr + 4, 1) + ":"
		+ byteToString(addr + 5, 1);
	return "Target Mac Address: " + res;
}

QString DataPackage::getArpSIpAddr()
{
	ARP_HEADER* arp;
	arp = (ARP_HEADER*)(pkt_content + 14);
	u_char* addr = arp->_src_ip_addr;
	QString res = QString::number(*addr) + "."
		+ QString::number(*(addr + 1)) + "."
		+ QString::number(*(addr + 2)) + "."
		+ QString::number(*(addr + 3));
	return "Sender Ip Address: " + res;
}

QString DataPackage::getArpTIpAddr()
{
    ARP_HEADER* arp;
    arp = (ARP_HEADER*)(pkt_content + 14);
    u_char* addr = arp->_des_ip_addr;
    QString res = QString::number(*addr) + "."
                  + QString::number(*(addr + 1)) + "."
                  + QString::number(*(addr + 2)) + "."
                  + QString::number(*(addr + 3));
    return "Target Ip Address: " + res;
}


/*************** 获取TCP数据 ***********************/
QString DataPackage::getTcpSrcPort()
{
    TCP_HEADER* tcp;
    tcp = (TCP_HEADER*)(pkt_content+34);
    u_short res = NTOHS(tcp->_sport);
    return QString::number(res);
}

QString DataPackage::getTcpDesPort()
{
    TCP_HEADER* tcp;
    tcp = (TCP_HEADER*)(pkt_content+34);
    u_short res = NTOHS(tcp->_dport);
    return QString::number(res);
}

QString DataPackage::getTcpSeq()
{
    TCP_HEADER* tcp;
    tcp = (TCP_HEADER*)(pkt_content+34);
    u_int res = NTOHSL(tcp->_seqNum);
    return "Sequence Number: " + QString::number(res);
}

QString DataPackage::getTcpAck()
{
    TCP_HEADER* tcp;
    tcp = (TCP_HEADER*)(pkt_content + 34);
    u_int res = NTOHSL(tcp->_ackNum);
    return "Acknowladge Number: " + QString::number(res);
}

/*************** 获取UDP数据 ***********************/

QString DataPackage::getUdpSrcPort()
{
    UDP_HEADER* udp;
    udp = (UDP_HEADER*)(pkt_content + 34);
    u_short res = NTOHS(udp->_sport);
    return QString::number(res);
}

QString DataPackage::getUdpDesPort()
{
    UDP_HEADER* udp;
    udp = (UDP_HEADER*)(pkt_content + 34);
    u_short res = NTOHS(udp->_dport);
    return QString::number(res);
}

QString DataPackage::getUdpLength()
{
    UDP_HEADER* udp;
    udp = (UDP_HEADER*)(pkt_content + 34);
    u_short res = NTOHS(udp->_len);
    return QString::number(res);
}

QString DataPackage::iptos(u_int in)
{
    u_char* p;
    p = (u_char*)&in;
    QString res="";
    res = QString::number(*(p + 3)) + "."
          + QString::number(*(p + 2)) + "."
          + QString::number(*(p + 1)) + "."
          + QString::number(*p);
    //memset(buf, 0x00, sizeof buf);
    //sprintf_s(buf, 512, "%d.%d.%d.%d", p[3], p[2], p[1], p[0]);
    return res;
}


/*************** 获取ICMP数据 ***********************/

QList<QTreeWidgetItem *> DataPackage::getIcmp()
{
    QList<QTreeWidgetItem*> info;
    info.append(new QTreeWidgetItem(QStringList() << getIcmpType()));
    info.append(new QTreeWidgetItem(QStringList() << getIcmpCode()));
    info.append(new QTreeWidgetItem(QStringList() << getIcmpCheckSum()));
    info.append(new QTreeWidgetItem(QStringList() << getIcmpId()));
    info.append(new QTreeWidgetItem(QStringList() << getIcmpSeq()));
    return info;
}

QString DataPackage::getIcmpType()
{
    ICMP_HEADER* icmp;
    icmp = (ICMP_HEADER*)(pkt_content + 34);
    u_char type = icmp->_type;
    u_char code = icmp->_code;
    if (code == 0)
    {
        if (type == 8)
        {
            return "Type: 8 (Echo (ping) request)";
        }
        else if (type == 0)
        {
            return "Type: 0 (Echo (ping) reply)";
        }
        else if (type == 11)
        {
            return "Type: 11 (Out of time)";
        }
    }
    else
    {
        return "Type: " + QString::number(type);
    }
}

QString DataPackage::getIcmpCode()
{
    ICMP_HEADER* icmp;
    icmp = (ICMP_HEADER*)(pkt_content + 34);
    u_char code = icmp->_code;
    return "Code: " + QString::number(code);
}

QString DataPackage::getIcmpCheckSum()
{
    ICMP_HEADER* icmp;
    icmp = (ICMP_HEADER*)(pkt_content + 34);
    u_short checkSum = NTOHS(icmp->_checkSum);
    char buf[1024];
    _itoa_s(checkSum, buf, 16);
    QString cs = buf;
    return "CheckSum: 0x" + cs;
}

QString DataPackage::getIcmpId()
{
    ICMP_HEADER* icmp;
    icmp = (ICMP_HEADER*)(pkt_content + 34);
    u_short id = NTOHS(icmp->_identification);
    char buf[1024];
    _itoa_s(id, buf, 16);
    QString sid = buf;
    return "Identifier: 0x" + sid;
}

QString DataPackage::getIcmpSeq()
{
    ICMP_HEADER* icmp;
    icmp = (ICMP_HEADER*)(pkt_content + 34);
    u_short seq = NTOHS(icmp->_seq);
    return "Sequence Number: " + QString::number(seq);
}


/*************** 获取DNS数据 ***********************/
QList<QTreeWidgetItem*> DataPackage::getDns()
{
    QList<QTreeWidgetItem*> info;
    info.append(new QTreeWidgetItem(QStringList() << getDnsId())); // 添加DNS事务ID
    QString question = getDnsQuestionNumber(); // 获取DNS问题数
    QString answer = getDnsAnswerNumber(); // 获取DNS回答数
    QTreeWidgetItem* flag = new QTreeWidgetItem(QStringList() << "Flags:"+getDnsFlags()); // 获取DNS标志
    flag->addChildren(getDnsFlagInfo()); // 获取DNS标志信息
    info.append(flag);
    info.append(new QTreeWidgetItem(QStringList() << "Qusetions: " + getDnsQuestionNumber())); // 添加DNS问题数
    info.append(new QTreeWidgetItem(QStringList() << "Answer RRs: " + getDnsAnswerNumber())); // 添加DNS回答数
    info.append(new QTreeWidgetItem(QStringList() << "Authority RRS: "+getDnsAuthorityNumber())); // 添加DNS授权资源记录数
    info.append(new QTreeWidgetItem(QStringList() << "Additional RRS: " + getDnsAdditionalNumber())); // 添加DNS附加资源记录数
    int offset = 0;
    if (question == "1") { // 如果有一个问题
        QString domainInfo;
        int Type;
        int Class;
        getDnsQueriesDomain(domainInfo, Type, Class); // 获取DNS查询域名
        QTreeWidgetItem* queryDomainTree = new QTreeWidgetItem(QStringList() << "Queries"); // 创建查询域名树
        info.append(queryDomainTree);
        offset += (4 + domainInfo.size() + 2); // 计算偏移量
        QString type = getDnsDomainType(Type); // 获取DNS域名类型
        QTreeWidgetItem* querySubTree = new QTreeWidgetItem(QStringList() << domainInfo + " type " + type + ", class IN"); // 创建查询子树
        queryDomainTree->addChild(querySubTree);
        querySubTree->addChild(new QTreeWidgetItem(QStringList() << "Name:" + domainInfo)); // 添加域名
        querySubTree->addChild(new QTreeWidgetItem(QStringList() << "[Name Length:" + QString::number(domainInfo.size()) + "]")); // 添加域名长度
        querySubTree->addChild(new QTreeWidgetItem(QStringList() << "Type:" + type + "(" + QString::number(Type) + ")")); // 添加类型
        querySubTree->addChild(new QTreeWidgetItem(QStringList() << "Class: IN (0x000" + QString::number(Class) + ")")); // 添加类
    }
    int answerNumber = answer.toUtf8().toInt(); // 获取回答数
    if (answerNumber > 0) { // 如果有回答
        QTreeWidgetItem* answerTree = new QTreeWidgetItem(QStringList() << "Answers"); // 创建回答树
        info.append(answerTree);
        for (int i = 0; i < answerNumber; i++) { // 遍历回答
            QString name1;
            QString name2;
            u_short type;
            u_short Class;
            u_int ttl;
            u_short length;

            int tempOffset = getDnsAnswersDomain(offset, name1, type, Class, ttl, length, name2); // 获取DNS回答域名
            QString sType = getDnsDomainType(type); // 获取DNS域名类型
            QString temp = "";
            if (type == 1) temp = "addr"; // 如果类型为1，设置为地址
            else if (type == 5) temp = "cname"; // 如果类型为5，设置为别名
            QTreeWidgetItem* answerSubTree = new QTreeWidgetItem(QStringList() << name1 + ": type " + sType + ",class IN, " + temp + ":" + name2); // 创建回答子树
            answerTree->addChild(answerSubTree);
            answerSubTree->addChild(new QTreeWidgetItem(QStringList() << "Name:" + name1)); // 添加域名
            answerSubTree->addChild(new QTreeWidgetItem(QStringList() << "Type:" + sType + "(" + QString::number(type) + ")")); // 添加类型
            answerSubTree->addChild(new QTreeWidgetItem(QStringList() << "Class: IN (0x000" + QString::number(Class) + ")")); // 添加类
            answerSubTree->addChild(new QTreeWidgetItem(QStringList() << "Time to live:" + QString::number(ttl) + "(" + QString::number(ttl) + " second)")); // 添加生存时间
            answerSubTree->addChild(new QTreeWidgetItem(QStringList() << "Data length:" + QString::number(length))); // 添加数据长度
            answerSubTree->addChild(new QTreeWidgetItem(QStringList() << sType + ":" + name2)); // 添加类型和域名

            offset += tempOffset; // 更新偏移量
        }
    }
    return info; // 返回信息列表
}

QList<QTreeWidgetItem*> DataPackage::getDnsFlagInfo()
{
    QList<QTreeWidgetItem*> info;
    info.append(new QTreeWidgetItem(QStringList() << "Response: " + getDnsFlagsQR()));
    info.append(new QTreeWidgetItem(QStringList() << "Opcode: " + getDnsFlagsOpcode()));
    info.append(new QTreeWidgetItem(QStringList() << "Authoritative: " + getDnsFlagsAA()));
    info.append(new QTreeWidgetItem(QStringList() << "Truncated: " + getDnsFlagsTC()));
    info.append(new QTreeWidgetItem(QStringList() << "Recursion Desired: " + getDnsFlagsRD()));
    info.append(new QTreeWidgetItem(QStringList() << "Recursion Available: " + getDnsFlagsRA()));
    info.append(new QTreeWidgetItem(QStringList() << "Z: " + getDnsFlagsZ()));
    info.append(new QTreeWidgetItem(QStringList() << "Reply code: " + getDnsFlagsRcode()));
    return info;
}

QString DataPackage::getDnsId()
{
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    u_short id = NTOHS(dns->_id);
    return "Transaction ID: 0x" + QString::number(id, 16);
}

QString DataPackage::getDnsFlags() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    int type = ntohs(dns->_flag);
    QString info = "";
    if ((type & 0xf800) == 0x0000) {
        info = "(Standard query)";
    }
    else if ((type & 0xf800) == 0x8000) {
        info = "(Standard query response)";
    }
    return "0x" + QString::number(type, 16) + info;
}

QString DataPackage::getDnsFlagsQR() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    u_char qr = (ntohs(dns->_flag) & 0x8000) >> 15;
    QString res = QString::number(qr);
    if (qr == 0)
    {
        res += " Message is a query";
    }
    else if (qr == 1)
    {
        res += " Message is a response";
    }
    return res;
}

QString DataPackage::getDnsFlagsOpcode() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);

    return QString::number((ntohs(dns->_flag) & 0x7800) >> 11);
}

QString DataPackage::getDnsFlagsAA() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number((ntohs(dns->_flag) & 0x0400) >> 10);
}

QString DataPackage::getDnsFlagsTC() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    u_char TC = (ntohs(dns->_flag) & 0x0200) >> 9;
    QString res = "Message is ";
    if (TC == 0)
    {
        res += "not truncated (" + QString::number(TC) + ")";
    }
    else if (TC == 1)
    {
        res += "truncated (" + QString::number(TC) + ")";
    }
    return res;
}

QString DataPackage::getDnsFlagsRD() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    u_char RD = (ntohs(dns->_flag) & 0x0100) >> 8;
    QString res = "";
    if (RD == 0)
    {
        res = "Don't do query recursively (" + QString::number(RD) + ")";
    }
    else if (RD == 1)
    {
        res = "Do query recursively (" + QString::number(RD) + ")";
    }
    return res;
}

QString DataPackage::getDnsFlagsRA() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number((ntohs(dns->_flag) & 0x0080) >> 7);
}

QString DataPackage::getDnsFlagsZ() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number((ntohs(dns->_flag) & 0x0070) >> 4);
}

QString DataPackage::getDnsFlagsRcode() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number((ntohs(dns->_flag) & 0x000f));
}

QString DataPackage::getDnsQuestionNumber() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number(ntohs(dns->_ques));
}

QString DataPackage::getDnsAnswerNumber() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number(ntohs(dns->_ans));
}

QString DataPackage::getDnsAuthorityNumber() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number(ntohs(dns->_auth));
}

QString DataPackage::getDnsAdditionalNumber() {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8);
    return QString::number(ntohs(dns->_add));
}

void DataPackage::getDnsQueriesDomain(QString& name, int& Type, int& Class) {
    DNS_HEADER* dns;
    dns = (DNS_HEADER*)(pkt_content + 14 + 20 + 8); // 获取DNS头部
    char* domain = (char*)(pkt_content + 14 + 20 + 8 + 12); // 获取域名部分
    while (*domain != 0x00) { // 遍历域名部分，直到遇到结束符0x00
        if (domain && (*domain) <= 64) { // 检查域名长度是否有效
            int length = *domain; // 获取域名长度
            domain++;
            for (int k = 0; k < length; k++) { // 读取域名
                name += (*domain);
                domain++;
            }
            name += ".";
        }
        else break; // 如果域名长度无效，跳出循环
    }
    domain++;
    name = name.left(name.length() - 1); // 去掉最后一个点
    DNS_QUESITON* qus = (DNS_QUESITON*)(domain); // 获取DNS查询部分
    Type = ntohs(qus->query_type); // 获取查询类型
    Class = ntohs(qus->query_class); // 获取查询类
}

QString DataPackage::getDnsDomainName(int offset) {
    char* dns;
    dns = (char*)(pkt_content + 14 + 20 + 8 + offset); // 获取DNS数据部分的指针
    QString name = "";
    while (dns && *dns != 0x00) { // 遍历DNS数据部分，直到遇到结束符0x00
        if ((unsigned char)(*dns) <= 64) { // 检查域名长度是否有效
            int length = *dns; // 获取域名长度
            dns++;
            for (int k = 0; k < length; k++) { // 读取域名
                name += (*dns);
                dns++;
            }
            name += ".";
        }
        else if (((*dns) & 0xc0) == 0xc0) { // 检查是否为指针
            int accOffset = (((*dns) & 0x3f) << 8); // 计算指针偏移量
            dns++;
            accOffset += (unsigned char)(*dns);
            name += getDnsDomainName(accOffset) + "."; // 递归获取域名
            dns++;
            break;
        }
    }
    name = name.left(name.length() - 1); // 去掉最后一个点
    return name;
}

int DataPackage::getDnsAnswersDomain(int offset, QString& name1, u_short& Type, u_short& Class, u_int& ttl, u_short& dataLength, QString& name2) {
    char* dns = (char*)(pkt_content + 14 + 20 + 8 + 12 + offset); // 获取DNS数据部分的指针
    if (((*dns) & 0xc0) == 0xc0) { // 检查是否为指针
        int accOffset = (((*dns) & 0x3f) << 8); // 计算指针偏移量
        dns++; //
        accOffset += (*dns); // 更新指针偏移量
        name1 = getDnsDomainName(accOffset); // 获取域名
        dns++; //
        DNS_ANSWER* answer = (DNS_ANSWER*)(dns); // 获取DNS回答部分
        Type = ntohs(answer->answer_type); // 获取回答类型
        Class = ntohs(answer->answer_class); // 获取回答类
        ttl = ntohl(answer->TTL); // 获取生存时间
        dataLength = ntohs(answer->dataLength); // 获取数据长度
        dns += (2 + 2 + 4 + 2); // 更新指针位置
        if (dataLength == 4) { // 如果数据长度为4
            for (int i = 0; i < 4; i++) { // 读取数据
                name2 += QString::number((unsigned char)(*dns)); // 将数据转换为字符串
                name2 += "."; // 添加点分隔符
                dns++; // 更新指针位置
            }
        }
        else { // 如果数据长度不为4
            for (int k = 0; k < dataLength; k++) { // 读取数据
                if ((unsigned char)(*dns) <= 64) { // 检查数据长度是否有效
                    int length = *dns; // 获取数据长度
                    dns++; // 更新指针位置
                    k++; // 更新计数器
                    for (int j = 0; j < length; j++) { // 读取数据
                        name2 += *dns; // 将数据转换为字符串
                        dns++; // 更新指针位置
                        k++; // 更新计数器
                    }
                    name2 += "."; // 添加点分隔符
                }
                else if (((*dns) & 0xc0) == 0xc0) { // 检查是否为指针
                    int accOffset = (((*dns) & 0x3f) << 8); // 计算指针偏移量
                    dns++; // 更新指针位置
                    k++; // 更新计数器
                    accOffset += (unsigned char)(*dns); // 更新指针偏移量
                    name2 += getDnsDomainName(accOffset) + "."; // 获取域名并添加点分隔符
                    dns++; // 更新指针位置
                    k++; // 更新计数器
                }
            }
        }
        name2 = name2.left(name2.length() - 1); // 去掉最后一个点
        return dataLength + 2 + 2 + 2 + 4 + 2; // 返回数据长度

    }
    else { // 如果不是指针
        name1 = getDnsDomainName(offset + 12); // 获取域名
        DNS_ANSWER* answer = (DNS_ANSWER*)(dns + name1.size() + 2); // 获取DNS回答部分
        Type = ntohs(answer->answer_type); // 获取回答类型
        Class = ntohs(answer->answer_class); // 获取回答类
        ttl = ntohl(answer->TTL); // 获取生存时间
        dataLength = ntohs(answer->dataLength); // 获取数据长度
        if (dataLength == 4) { // 如果数据长度为4
            dns += (2 + 2 + 4 + 2 + name1.size() + 1); // 更新指针位置
            for (int i = 0; i < 4; i++) { // 读取数据
                name2 += (QChar)(*dns); // 将数据转换为字符
                dns++; // 更新指针位置
            }
        }
        else { // 如果数据长度不为4
            for (int k = 0; k < dataLength; k++) { // 读取数据
                if ((unsigned char)(*dns) <= 64) { // 检查数据长度是否有效
                    int length = *dns; // 获取数据长度
                    dns++; // 更新指针位置
                    k++; // 更新计数器
                    for (int j = 0; j < length; j++) { // 读取数据
                        name2 += *dns; // 将数据转换为字符串
                        dns++; // 更新指针位置
                        k++; // 更新计数器
                    }
                    name2 += "."; // 添加点分隔符
                }
                else if (((*dns) & 0xc0) == 0xc0) { // 检查是否为指针
                    int accOffset = (((*dns) & 0x3f) << 8); // 计算指针偏移量
                    dns++; // 更新指针位置
                    k++; // 更新计数器
                    accOffset += (*dns); // 更新指针偏移量
                    name2 += getDnsDomainName(accOffset); // 获取域名
                    dns++; // 更新指针位置
                    k++; // 更新计数器
                }
            }
        }
        name2 = name2.left(name2.length() - 1); // 去掉最后一个点
        return dataLength + 2 + 2 + 2 + 4 + 2 + name1.size() + 2; // 返回数据长度
    }
}

// 获取DNS域名类型
QString DataPackage::getDnsDomainType(int type) {
    switch (type) {
    case 1: return "A (Host Address)";  // 主机地址
    case 2:return "NS";  // 名称服务器
    case 5:return "CNAME (Canonical NAME for an alias)";  // 规范名称
    case 6:return "SOA";  // 起始授权机构
    case 11:return "WSK";  // 反向映射
    case 12:return "PTR";  // 指针记录
    case 13:return "HINFO";  // 主机信息
    case 15:return "MX";  // 邮件交换记录
    case 28:return "AAAA";  // IPv6地址记录
    case 252:return "AXFR";  // 区域传送
    case 255:return "ANY";  // 任意记录
    default:return "";  // 未知类型
    }
}




QString DataPackage::byteToString(u_char* str, int size)
{
    QString res = "";
    for (int i = 0; i < size; i++)
    {
        // 获取高4位
        char one = str[i] >> 4;
        if (one >= 0x0A)
            one += 0x41 - 0x0A;  // 转换为字母
        else one += 0x30;  // 转换为数字
        // 获取低4位
        char two = str[i] & 0xF;
        if (two >= 0x0A)
            two += 0x41 - 0x0A;  // 转换为字母
        else two += 0x30;  // 转换为数字
        // 追加到结果字符串
        res.append(one);
        res.append(two);
    };
    return res;
}
